﻿using ThresholdAssistant.ConfigSdk;
using System;

namespace ThresholdAssistant.Tools
{
    /// <summary>
    /// 雪花算法Id号码生成工具
    /// </summary>
    public static class SnowflakeNoUtil
    {
        /// <summary>
        /// 自增开始位置
        /// </summary>
        private static long Sequence = 10000000L;

        /// <summary>
        /// 对象锁
        /// </summary>
        private static readonly object @lock = new object();

        /// <summary>
        /// 随机生成机器人码
        /// </summary>
        private static readonly string WebAppId = $"{new Random().Next(100, 999)}";

        /// <summary>
        /// 时间段
        /// </summary>
        private static long RefSequence = long.Parse(DateTime.Now.Date.AddDays(1).ToString("yyyyMMddHHmmssffff"));

        /// <summary>
        /// 静态构造函数
        /// </summary>
        static SnowflakeNoUtil()
        {
            try
            {
                var appId = BootstrapJson.Configuration?.GetValue("SnowflakeNo:AppId");
                if (!string.IsNullOrWhiteSpace(appId))
                {
                    WebAppId = appId;
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 获取流水号
        /// </summary>
        /// <param name="serialType">流水号类型</param>
        /// <param name="suffix">前缀</param>
        /// <returns></returns>
        public static string GetSerialNo(int serialType = 0, string suffix = "")
        {
            var serialNo = NextId(suffix);
            if (string.IsNullOrWhiteSpace(serialNo))
            {
                throw new Exception($"GetSerialNo({serialType}): 获取序列号失败。");
            }
            return serialNo;
        }

        /// <summary>
        /// 生成当前时间戳
        /// </summary>
        /// <returns></returns>
        private static long TimeGen()
        {
            return long.Parse(DateTime.Now.ToString("yyyyMMddHHmmssffff"));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="suffix">后缀</param>
        /// <returns></returns>
        private static string NextId(string suffix)
        {
            lock (@lock)
            {
                var timestamp = TimeGen();
                if (RefSequence < timestamp)
                {
                    Sequence = 10000000L;
                    RefSequence = long.Parse(DateTime.Now.Date.AddDays(1).ToString("yyyyMMddHHmmssffff"));
                }
                Sequence += 1;
                var nextId = $"{timestamp}{WebAppId}{Sequence}{suffix}";
                return nextId;
            }
        }
    }
}